Shapes
QuickDraw GX uses 13 basic types of shape object, each of which is specified by a different value for the shape type property. Figure 3-5 shows an example of each of the shape types.
The following four sections examine these shape types by category: geometric shapes, bitmap shapes, picture shapes, and typographic shapes.
Geometric Shapes
QuickDraw GX provides eight types of geometric shapes: empty shapes,
full shapes, point shapes, line shapes, curve shapes, polygon shapes, and
path shapes. Each of these types of shapes represents a different class of geometric image.The empty shape type and the full shape type are special types of geometric shapes. An empty shape represents a shape with no geometry--it has no geometric points, it has no lines or curves, and it covers no area. A full shape represents a shape that covers the maximum possible area--it also has no geometric points, because none are necessary to define it.
Figure 3-6 shows examples of the other six types of geometric shapes.
Figure 3-6 Sample geometric shapes
Basically, geometric shapes are the shapes that can be described using a series of geometric points. These points define the position of the endpoints and corner points of the geometric shapes. For example, a line can be described by two geometric points: the point specifying the beginning of the line and the point specifying the end of the line. A curve can be described with three geometric points: a first point, a last point, and an off-curve control point.
When you create a geometric shape, you specify the geometric points that define the shape. QuickDraw GX stores these points in the geometry property of the shape. Therefore, the geometry property of a point shape contains a single geometric point. The geometry property of a line shape contains two geometric points. The geometry of a curve shape contains three geometric points, and so on.
Figure 3-7 shows how three different types of geometric shapes use their geometries to define their basic structures.
Figure 3-7 Sample shape geometries
In this figure, the endpoints are represented by small round dots and the off-
curve control points are represented by small squares.Figure 3-7 shows:
Whenever your application no longer needs a shape, you should dispose of the shape by calling the
- A line geometry, which consists of two geometric points: a first point and a last point. QuickDraw GX connects these points with a straight line.
- A curve geometry, which consists of three geometric points: a first point, an off-curve control point, and a last point. QuickDraw GX connects the first and last point with a quadratic Bézier curve. The off-curve control point is used to determine the tangents of the curve.
- A path geometry, which consists of a series of geometric points and control bits that indicate which points are on-curve points (endpoints or corner points) and which points are off-curve control points (which determine tangents of curves). QuickDraw GX builds path shapes out of straight lines and curved lines.
GXDisposeShape
function. This function
This process is the same for most types of objects: styles, inks, transforms, and so on.
- decrements the value of the owner count property of the shape
- determines if the resulting owner count is 0, in which case QuickDraw GX frees the memory used by the shape
Remember that the owner count property of a shape object reflects how many references to the shape exist. When you create a shape, you typically store a reference to it in one of your application's variables. Therefore, QuickDraw GX always initializes the owner count of a new shape object to 1.
Creating Geometric Shapes
Once you have created a structure of the appropriate type to represent the geometry of your desired shape, you can create a shape object with either of the methods described in "Creating and Copying Shapes" on page 69.To create geometric shapes using the second of those methods, your application first needs to create geometry structures that contain the geometric points that define the shape. QuickDraw GX provides a data type for each type of geometry structure. For example, a line geometry is represented by a line structure, as defined by the
gxLine
data type:
struct gxLine { struct gxPoint first; struct gxPoint last; }A line structure contains two point structures: one for each point.Figure 3-8 shows an example line structure and the line it represents.
As another example, the polygon structure is relatively more complex:
struct gxPolygon { long vectors; struct gxPoint vector[gxAnyNumber]; };The definition of thegxPolygon
data type uses the array index constantgxAnyNumber
to indicate that the type defines a variable-length structure.
A polygon structure has two fields:
A polygon structure represents a single polygon contour--a series of points connected by straight lines.
- The first field contains a number indicating the total number of points in the polygon.
- The second field contains a variable-length array of the points themselves (stored in point structures).
Multiple polygon contours can be combined into a single structure using the
- IMPORTANT
- Although a polygon structure represents a single polygon contour, a single polygon shape, however, can include any number of individual polygon contours in its geometry.<8bat>s
![]()
gxPolygons
data type:
struct gxPolygons { long contours; struct gxPolygon contour[gxAnyNumber]; }This multiple-polygon structure has two fields:
Since these multiple-polygon structures are variable-length, you do not declare and initialize them in the normal manner. Instead, you typically define them as an array of long integers:
- The first contains a number representing the total number of polygon contours.
- The second contains a variable-length array of the polygon contours themselves (stored in polygon structures).
long twoPolygons[] = {2, /* number of polygon contours */ 3, /* number of points in first contour */ ff(0), ff(100), /* first point */ ff(50), ff(0), /* second point */ ff(100), ff(100), /* third point */ 4, /* number of points in second contour */ ff(0), ff(150), /* first point */ ff(100), ff(150), /* second point */ ff(100), ff(200), /* third point */ ff(0), ff(200)}; /* fourth point */Then, when you need to use this array as agxPolygons
structure, you cast it to the correct type using this expression:
(gxPolygons *) twoPolygonsFigure 3-9 shows thetwoPolygons
structure and the polygon contours that it represents.Figure 3-9 A polygons structure
Path shapes are similar to polygon shapes, except path shapes include control bits that specify which points are on the path (that is, which points are end points and corner points) and which points are off the path (that is, which points are off-curve control points).
Drawing Geometric Shapes
After you have created a shape object, you can draw your shape using theGXDrawShape
function.Using shape objects to represent your graphics shapes provides many benefits to your application: you can redraw the shape at any time with no added preparation, you can edit the shape and draw the edited version, you can copy the shape, you can draw it to multiple view ports, and so on.
However, there are occasions when you do not want the overhead of having to create and maintain a shape object. QuickDraw GX provides the type-specific drawing functions for these situations. These functions include
GXDrawPoint
,GXDrawLine
,GXDrawCurve
,GXDrawRectangle
,GXDrawPolygons
, andGXDrawPaths
. Each of these functions
These functions create a shape object and then dispose of it every time you draw a geometry, so you should only use these functions when you know
- takes a geometry structure as a parameter
- encapsulates the geometry into a temporary shape of the appropriate type (using the information in the default shape for every property besides the geometry)
- draws the temporary shape
- disposes of the temporary shape
you want to draw a geometry only one time. If you want to draw the same geometry more than once, you should create a shape object and use theGXDrawShape
function to draw it.Editing Geometric Shape Geometries
Once you've created a geometric shape object, you can change its geometry using a number of methods:
QuickDraw GX also provides a great number of geometric operations that allow you to manipulate shape geometries. Some of these operations calculate information based on a shape's geometry. Here are some examples:
- You can completely replace the geometry with a new geometry using
the appropriate function:GXSetPoint
,GXSetLine
,GXSetCurve
,GXSetRectangle
,GXSetPolygons
, orGXSetPaths
.- You can copy the geometry from one shape to another using the
GXSetGeometry
function. This function also changes the target shape's shape type to the source's shape type if they aren't the same.- You can edit the geometry directly, but this requires several additional steps and extra care. You can use the
GXLockShape
function to lock the shape's geometry into a fixed memory location, use theGXGetShapeStructure
function to get a pointer to the locked geometry, edit the contents of the geometry directly, use theGXChangedShape
function to notify QuickDraw GX that you have edited the contents of the geometry, and then use theGXUnlockShape
function to allow QuickDraw GX to relocate the geometry,
as necessary.- You can replace an individual geometric point or a range of geometric points in the shape's geometry using the
GXSetShapePoints
function.- You can replace a range of geometric points in the shape's geometry with the geometry of another shape using the
GXSetShapeParts
function.- If the shape is a polygon or path shape, you can use the
GXSetPolygonParts
orGXSetPathParts
function to replace a range of geometric points in the shape's geometry with points you specify in agxPolygons
orgxPaths
structure.
Other geometric operations perform geometric arithmetic with the geometries of two shapes. Here are some examples:
- The
GXGetShapeLength
function calculates the length of a shape's contours.- The
GXGetShapeCenter
function calculates the center point of a shape.- The
GXGetShapeArea
function calculates the area enclosed by a shape's contours.
- The
GXIntersectShape
function calculates a geometry that describes the area contained by both shapes.- The
GXUnionShape
function calculates a geometry that describes the area contained by either shape.- The
GXExcludeShape
function calculates a geometry that describes the area contained by either shape but not by both shapes.
Specifying Shape Fill
The geometric shapes use the value of their shape fill property, in conjunction with their geometry property, to determine the basic geometric structure of the shape. QuickDraw GX provides four basic types of shape fills:
Figure 3-10 shows how these shape fills affect the drawing of three
- No fill, which indicates that the shape should not be filled at all--that is, the shape covers no area and does not appear when drawn.
- Framed fills, which indicate that QuickDraw GX should draw the shape as a series of connected lines and curves. A special case of a framed fill is the hollow fill, which indicates that the contours of the shape should be closed--that is, the last point of every contour is connected to the first point of
the contour.- Solid fills, which indicate that QuickDraw GX should draw the shape as the area enclosed by the shape's contours. A special case of a solid fill is the winding fill, which indicates that overlapping areas in the shape's geometry should also be filled.
- Inverse fills, which indicate that QuickDraw GX should draw the shape as the area not enclosed by the shape's contours.
sample shapes.Figure 3-10 How the basic types of shape fills affect shapes
Not every shape fill type is appropriate for every type of geometric shape. For example, a line shape can have a open-frame shape fill, but not a hollow fill or a solid fill. A rectangle can have a hollow fill or a solid fill, but not an open-
frame shape fill. Polygon and path shapes can have any kind of shape fill.To determine the value of the shape fill property of a shape object, you can use the
GXGetShapeFill
function. To set a shape's shape fill, you can use theGXSetShapeFill
function.For detailed information about shape fills, see Inside Macintosh: QuickDraw GX Graphics.
Converting Between Shape Types
QuickDraw GX also provides theGXGetShapeType
function, which allows you to determine the shape type of a shape, and theGXSetShapeType
function, which allows you to set the shape type of a shape.When you change a shape's shape type using the
GXSetShapeType
function, QuickDraw GX performs a shape type conversion on the shape's geometry and shape fill properties. The shape type conversion performed differs depending on the type you are converting from and the type you are converting to. Some examples of converting between geometric shape types are:
You can also convert between geometric shapes and other types of shapes in most situations.
- If you convert a line shape to a polygon shape, the resulting polygon has one contour, which matches the original line.
- If you convert a polygon shape to a line shape, QuickDraw GX makes the line shape geometry out of the first two geometric points of the polygon shape. All the other information in the original polygon geometry is lost.
- If you convert a polygon shape to a path shape, QuickDraw GX copies all
of the geometric points from the original polygon shape geometry into
the resulting path shape geometry. All of the points in the resulting path shape are on-curve points and the resulting path exactly matches the original polygon.- If you convert a path shape to a polygon shape, QuickDraw GX creates a new polygon shape that approximates the original path shape. You can specify how closely you want the approximation to match the original using the curve error property of the shape's style object.
For complete information about converting between shape types, see , as well as Inside Macintosh: QuickDraw GX Graphics. and Inside Macintosh: QuickDraw GX Typography.
- You can convert any geometric shape to a picture shape. The resulting picture shape contains one item: the original shape.
- You can convert any shape (except picture and full shapes) to a bitmap shape. QuickDraw GX creates a bitmap shape with the same boundaries
as the original shape and draws the shape into the new bitmap.- You can convert a glyph shape to a path shape. The geometry of the resulting path shape represents the outlines of the glyphs in the original glyph shape.
Hit-Testing Geometric Shapes
Hit-testing is the process of converting a point in the displayed representation of a shape, called the hit point, to a location in the shape's geometry. For example, when a user presses the mouse button, hit-testing can tell you which shape, and which part of that shape, the cursor was close to at that moment.You can use hit-testing to select shapes, or specific parts of shapes, for highlighting and for user manipulation, as described in detail in Chapter 6, "Handling Graphics," and in Chapter 7, "Handling Typography."
You use the function
GXHitTestShape
to hit-test geometric shapes. Before
you hit-test a shape, you use the hit-test parameters property of the shape's transform object. These parameters allow you to specify the tolerance of the hit-test--how close the hit point must be to be considered a hit--and what parts of the shape to hit-test against.Figure 3-11 shows an example of hit-testing a line shape.
Figure 3-11 Hit testing a line shape
Although the hit point does not actually touch the line shape in this example, the tolerance of the hit-test (stored in the hit-test parameters property of the line's transform object) is such that the hit point is considered a successful hit. This figure also shows two parts of the line that are hit by the hit point. The hit point hits both the line's geometry part and the line's pen part. For each shape, you can specify which parts QuickDraw GX hit-tests against.
For more information about geometric shapes, see Inside Macintosh: QuickDraw GX Graphics.. For more information about hit-testing, see
.Bitmap Shapes
Bitmap shapes are a special kind of graphics shape that contain pixel images. They can be black and white, grayscale, or color. You specify the color value of each pixel.Although geometric shapes create images with more flexibility--they can be rendered by QuickDraw GX accurately at any output device resolution--bitmap shapes are still useful in a number of situations. For example, if you know the resolution of an output device, you can create a bitmap shape to use as an offscreen graphics buffer. As another example, since bitmaps allow you to specify multiple colors within a single shape, you can use bitmaps to create ramps--images that fade smoothly from one color to another.
Figure 3-12 shows some sample bitmaps.
Figure 3-12 Sample bitmap shapes
The geometry of a bitmap shape contains all the information necessary to recreate the pixel image, including the dimensions of the image, the color value of each pixel, and the color space used to specify the pixel color values.
Creating Bitmap Structures
A bitmap geometry is represented by a bitmap structure, which is defined by the gxBitmap data type. A bitmap structure has eight fields:
The geometry of a bitmap shape has one piece of information not contained in a bitmap structure--the position of the upper-left corner of the bitmap. This value you must set programmatically.
- A pointer to the pixel image--a two dimensional array of pixel values. Each pixel value specifies the color of one pixel in the image.
- The bitmap width--the number of pixels in each row of the bitmap.
- The bitmap height--the number of pixels in each column of the bitmap.
- The pixel size--the number of bits required to represent the color value of each pixel of the bitmap. For example, a black-and-white bitmap uses a pixel size of 1--the color of each pixel can be specified using a single bit.
- The bytes per row--the number of bytes of the pixel image that correspond to each row of the bitmap.
- The color space--the color space in which the pixel color values are specified.
- The color set--the array of color values from which the pixel colors are specified.
- The color profile--color-matching information for the device on which the bitmap was created.
Figure 3-13 shows a bitmap geometry and pixel image.
Figure 3-13 A bitmap geometry and a pixel image
In this example, the pixel size is 1, indicating that the color value of each pixel in the bitmap can be specified with a single bit. In other words, the bitmap uses a color set with two colors--in this case, white and black. The bytes per row is 2, indicating that 2 bytes are necessary to represent each row of the bitmap.
QuickDraw GX allows you to store a bitmap shape's pixel image in one of three places:
Bitmap shapes don't make much use of their style object. The only pieces of information a bitmap shape uses from its style object are the flags contained in the style attributes property that determine whether the upper-left corner of the bitmap is constrained to integer grid positions.
- You can have QuickDraw GX allocate memory for the pixel image in QuickDraw GX memory. In this case, you can use QuickDraw GX
functions to edit the contents of the pixel image.- You can allocate memory for the pixel image in your application memory. In this case, you provide QuickDraw GX a pointer to the memory containing the pixel image.
- You can associate the bitmap with a disk-based pixel image. In this case, the entire pixel image resides on disk--QuickDraw GX does not load it into memory. You can use this type of bitmap for very large pixel images that exceed your memory limitations.
Because bitmap shapes store their own color information in their geometries, they also don't use the information in the color property of their ink object. However, they do use the transfer mode property.
Bitmap shapes do make full use of their transform objects. You can clip, map, and hit-test bitmap shapes as well as draw them to multiple view ports.
Editing and Drawing Bitmap Shapes
Here are two ways you can create a bitmap shape:
Once you've created a bitmap shape, you can edit it using the bitmap-editing functions or, if the pixel image is in your application memory or on disk, you can edit the pixel image directly.
- You can pass the
gxBitmapType
constant to theGXNewShape
function, which creates a new copy of the default bitmap shape. The default geometry represents an empty bitmap--a bitmap height of 0, a bitmap width of 0,
and no pixel image. You can change this initial bitmap geometry using
the bitmap-editing functions:GXSetBitmap
,GXSetBitmapParts
, andGXSetShapePixel
.- You can create a bitmap structure and encapsulate it in a bitmap shape using the
GXNewBitmap
function. You specify whether you want your pixel image in QuickDraw GX memory, in application memory, or on disk using the fields of the bitmap structure.
You can draw a bitmap shape using the
GXDrawShape
function. You can also use theGXDrawBitmap
function to draw a bitmap. You provide a bitmap structure to this function, which encapsulates it into a temporary bitmap shape, draws the shape, and disposes of the shape. Only use this function if you know you want to draw a particular pixel image exactly once; otherwise, create a bitmap shape and useGXDrawShape
.Creating Offscreen Bitmaps
One important use of bitmap shapes is to create an offscreen buffer into which you can render other shapes. You can use these offscreen buffers, for example, to render complicated graphics offscreen and then copy to the screen complete, or you can use a double-buffering system to smooth the appearance of redrawing when giving user feedback.To create an offscreen bitmap, you create a bitmap to store the offscreen pixels and you create a view device object to represent the offscreen drawing world. You also create a view port object and connect it to this view device object. Then, when you want to draw a shape offscreen, you set the view port list of the shape's transform object to reference this offscreen view port. When you draw the shape, QuickDraw GX renders the shape into the pixel image of the offscreen bitmap.
The last recipe in Chapter 6, "Handling Graphics," shows an example of using offscreen bitmaps.
Hit-Testing Bitmap Shapes
QuickDraw GX allows you to hit-test bitmap shapes using theGXHitTestShape
function. However, the only shape part that QuickDraw GX hit-tests bitmaps against is the bounds part, which identifies the bounding rectangle of the shape. In other words, you can tell if a hit point hits a bitmap shape (within a certain tolerance), but you can't get any more information about where the bitmap shape was hit.For complete information about bitmap shapes, see Inside Macintosh: QuickDraw GX Graphics..
Picture Shapes
Picture shapes contain collections of other shapes. They allow you to gather disparate elements together inside a single shape.You can use picture shapes for many reasons, including to group a page of shapes together for printing, to provide a grouping feature in a graphics application, or to simplify your programming by gathering a number of shapes together and applying modifications to the group as a whole.
Figure 3-14 shows some example picture shapes. The bitmap in the middle and right-hand pictures is the ramp that serves as a lawn.
Figure 3-14 Sample picture shapes
Each shape in a picture is called a picture item. The geometry of a picture shape contains a list of references to the picture items in the picture. A picture item can be picture itself, which means that you can have picture hierarchies--pictures containing pictures containing other pictures.
Each picture item is a shape; therefore, each picture item has its own style object, ink object, and transform object. However, QuickDraw GX allows you to use a picture shape's geometry to specify an overriding style, overriding ink, and overriding transform object for each item in a picture.
As an example, you could collect into a picture a group of shapes that all had different colors specified in their individual ink objects. You could then create an ink object that specified a particular color--say blue. You could specify that each item in the picture use the new ink object as an overriding ink object. When you draw any one of the original shapes individually, it would still appear in its original color. However, when you draw the picture shape, every shape in the picture would be blue. (You don't have to provide the same overriding ink for every item, however--you could override half the items to be blue and half to be red, for example.)
Picture shapes don't use their own style and ink objects, since each shape in them has its own individual stylistic and color information. However, a picture shape does use its transform object--you can clip, map, and hit-test picture shapes as well as draw them to multiple view ports.
Creating, Editing, and Drawing Picture Shapes
Here are two ways you can create picture shapes:
Once you've created a picture shape, you can edit it using the picture-editing functions and draw it using the
- You can pass the
gxPictureType
constant to theGXNewShape
function, which creates a new copy of the default picture shape. Initially, the geometry of the new picture shape represents an empty picture--a picture with no picture items. You can then build a picture using the picture-editing functions:GXSetPicture
andGXSetPictureParts
.- You can create an array of references to shapes (as well as arrays of references to any overriding styles, inks, and transforms that you want to use) and then use the arrays to initialize the geometry of a new picture
using theGXNewPicture
function.
GXDrawShape
function.When you add a shape to a picture, QuickDraw GX allows you to specify whether the picture should contain a reference to the original shape or whether the shape should be copied and the picture should contain a reference to the copy. If the shapes are copied, all of their supporting objects are copied as well. You specify whether QuickDraw GX should copy items by setting the unique items shape attribute flag of the shape attributes property of the picture's
shape object.You can also use the
GXDrawPicture
function to draw a picture. You provide an array of references to other shapes and the function encapsulates the array into a temporary picture shape, draws the picture, and disposes of the picture shape. Only use this function if you know you want to draw a particular picture exactly one time.Hit-Testing Picture Shapes
QuickDraw GX provides theGXHitTestPicture
function for powerful hit-
testing of picture shapes. This function allows you to specify parameters about how to hit-test the picture shape, determines which shape in the picture was hit, and even determines which part of the shape was hit.See Chapter 6, "Drawing and Hit-Testing Graphics," for examples of hit-testing picture shapes. For complete information about picture shapes, see Inside Macintosh: QuickDraw GX Graphics.
Typographic Shapes
QuickDraw GX provides three types of typographic shapes: text shapes, glyph shapes, and layout shapes. In general, these shapes act much like other types of shapes, the unique characteristics of the shape being stored in the shape's geometry. In most situations, you can treat these shapes as graphics shapes--that is, you can apply a color and transfer mode to them and also you can clip and map them.Each of the three types of typographic shapes has different capabilities to make them suited for different uses in your application. Text shapes represent a line of text drawn with a single text size and typestyle. Glyph shapes represent a series of glyphs, each of which can have its own style, its own position, its own scaling factor, and its own rotation. Because they represent a line of text drawn in a typographically sophisticated manner, layout shapes use more information from the font than the other typographic shapes.
Each of these shapes uses its geometry in a slightly different way. The text shape stores simple information in its geometry about what its characters are and where to draw them. Text shapes store their stylistic information in their style objects, with a single style object containing stylistic information for the whole text shape.
Glyph and layout shapes, however, can have multiple styles. Since the style object can store information about only one single typestyle, glyph and layout shapes use their geometries to store their extra stylistic information.
Figure 3-15 shows the structure of the geometries of the typographic shapes.
Figure 3-15 Geometries of typographic shapes
Text Shapes
The text shape is the simplest of the QuickDraw GX typographic shapes. A text shape is a string of characters all drawn with the same stylistic information.Text shapes use the geometry property of their shape object to store three pieces of information:
Text shapes use the typographic properties of their style object, which include font, text size, and text face.
- the total number of characters (for example, 20)
- the text string (for example,
"This is a text shape"
)- the position of the text shape (for example, (50.0, 50.0))
Figure 3-16 shows how different values for these style properties affect the way a text shape appears when drawn.
Figure 3-16 A text shape drawn using three different style objects
Because a text shape has only one style, it is most useful for drawing nonfor-
matted text, such as text used in dialog boxes, terminal emulation programs, or primitive text editors. Text shapes draw faster than other types of typographic shapes, but they are far less powerful. You would not, for example, use text shapes for mixed-script text. If you need to draw text vertically or to draw text from right to left, you would use a layout shape.You cannot use a text shape to clip another shape, or to pattern or dash another shape. However, you can convert a text shape to a glyph shape or a path shape and then use that glyph shape for these purposes.
Text shapes use their ink and transform objects just as other shapes do. That is, you can color a text shape, apply a transfer mode to a text shape, clip a text shape, apply a transformation mapping to a text shape, hit-test a text shape, and draw a text shape to multiple view ports.
Glyph Shapes
Unlike text shapes, glyph shapes are typographic shapes that can contain multiple styles. In addition, you can vary the position, rotation, and scaling factor of each glyph in the shape.
Figure 3-17 shows how a sample glyph shape appears when drawn.
- Note
- A character is the concept of a particular typographic element: for example, lowercase a or the number 3. A glyph is the concrete form that represents the character (or group of characters). As an example, the fi ligature is internally represented by two characters but is visually represented by a single glyph. Be sure you do not confuse the terms glyph and glyph shape--a glyph shape can represent
many glyphs.)<8bat>u![]()
Figure 3-17 Sample glyph shape
In this glyph shape, each glyph has a different style (font, text size, text face, and so on), as well as a different position, rotation, and scaling factor, from the preceding glyph.
Like text shapes, glyph shapes store a character count and a string of text in their geometry property. Instead of a single position for the entire shape, however, a glyph shape can have positions for each of its glyphs. Similarly, a glyph shape geometry contains rotation and scaling factor information for
its glyphs as well as stylistic information for its glyphs. That's right--if a glyph shape uses more than one style, it stores the different styles in the geometry property of its shape object.Glyph shapes are most commonly used to achieve special graphics effects. For example, since you can position each glyph in a glyph shape individually, you can use a glyph shape to set text along a path--for example, a circle. You can also use glyph shapes to define the clip area of another shape--for example,
to clip glyphs out of a bitmap ramp shape. Additionally, you can use glyph shapes to pattern or dash other shapes.Glyph shapes use their ink and transform objects just as text shapes do.
Layout Shapes
The layout shape is the most sophisticated type of typographic shape. Like glyph shapes, layout shapes can contain multiple styles. Layout shapes allow you to
Figure 3-18 shows how a sample layout shape appears when drawn. Notice the ligatures (fi, ft, is, ct, ffi, and es) and the contextual forms of glyphs (the initial T and the final e of the word The).
- display ligatures automatically
- use contextual forms of glyphs automatically
- justify text in sophisticated ways, including language-specific justifications
- rearrange text for other languages automatically
- highlight selected text, including discontiguous highlighting for text with multiple directions
- hit-test within text
- determine the caret location for some position within the text
- decide where to break lines of text
Figure 3-18 Sample layout shape
Layout shapes use their style, ink, and transform shapes in a manner similar to glyph shapes.
Layout shapes present a sophisticated and powerful typographic tool. You
can find more information about them in Chapter 7, "Handling Typography." For complete information about typographic shapes, see Inside Macintosh: QuickDraw GX Typography.Creating and Drawing Typographic Shapes
The simplest typographic shape is the text shape. You can create a new text shape with theGXNewText
function:
gxPoint textPosition = {ff(50), ff(150)}; gxShape aTextShape = GXNewText(10, "Some text!", &textPosition);This function takes three parameters, corresponding to the three fields of a text shape geometry. As with all shapes, you can draw the text shape using theGXDrawShape
function:You can also draw text by using the
GXDrawText
function. This function is similar to the geometric functionsGXDrawPoint
,GXDrawLine
,GXDrawRectangle
, and so on. These functions all create a temporary shape object, draw the shape, and then dispose of the shape. Therefore, you should use these functions only if you know you want to draw a shape only one time.To create a glyph shape, QuickDraw GX provides the
GXNewGlyphs
function. This function takes seven parameters:
You can specify
- the number of characters in the text
- the string of characters
- an array of points specifying the position of each glyph
- an array of bits specifying how to position each glyph
- an array of tangents specifying the scaling and rotation of each glyph
- an array specifying how many glyphs use each style in the style array
- an array of styles
nil
for some of these parameters to use default values for fields of your glyph geometry.As a simple example, to create a glyph shape with two styles, you first create an array containing references to two style objects:
gxStyle myStyles[2];Then you create the style objects using theGXNewStyle
function:
myStyles[0] = GXNewStyle(); myStyles[1] = GXNewStyle();Then you initialize the style objects using theGXSetStyleTextSize
function, theGXSetStyleFont
function, and theFindCNameFont
library function from the font library. For example:
GXSetStyleTextSize(myStyles[0], ff(48)); GXSetStyleFont(myStyles[0], FindCNameFont(gxFullFontName, "Palatino")); GXSetStyleTextSize(myStyles[1], ff(32)); GXSetStyleFont(myStyles[1], FindCNameFont(gxFullFontName, "Helvetica"));You also need to create an array that indicates how many glyphs use each of these styles:
short myStyleRuns[2]; myStyleRuns[0] = 2; /* two glyphs use first style */ myStyleRuns[1] = 3; /* three glyphs use second style */Now you create a glyph shape with two styles:
gxShape aGlyphShape; aGlyphShape = GXNewGlyphs(5, "glyph", nil, nil, nil, myStyleRuns, myStyles);You use theGXMoveShapeTo
function to position the entire shape:
GXMoveShapeTo(aGlyphShape, ff(50), ff(150));and then draw the shape usingGXDrawShape
:
GXDrawShape(aGlyphShape);The resulting shape is shown in Figure 3-19.Figure 3-19 A glyph shape with two styles
You can create a layout shape using the
GXNewLayout
function. This function requires many parameters to initialize a layout shape. Here is an example that creates a layout shape with font features such as ligatures and contextual forms. (This example uses theInitializeRunControls
library function.)
char *sampleText = "This is QuickDraw GX!"; gxPoint layoutPosition = {ff(5), ff(60)}; gxRunControls runControls; gxRunFeature runFeatures[kTotalNumOfRunFeatures]; gxStyle styles[kTotalNumOfPieces]; gxShape tempLayoutShape; short totalLengthOfLayout, lengthsArray[kTotalNumOfPieces], loop; /* initialize layout run controls to default values */ InitializeRunControls(&runControls); /* create a single style for the entire layout shape */ styles[0] = NewLayoutStyle((char *)"\pHoefler Italic", ff(58), 0, &runControls, nil, 0, nil); /* turn on ligatures */ runFeatures[0].featureType = ligaturesType; runFeatures[0].featureSelector = ligatureRareOnSelector; /* turn on contextual forms */ runFeatures[1].featureType = characterAlternativesType; runFeatures[1].featureSelector = 1; GXSetStyleRunFeatures(styles[0], 2, runFeatures); /* set length of text */ lengthsArray[0] = 21; totalLengthOfLayout = 21; /* create layout shape */ tempLayoutShape = GXNewLayout(1, &totalLengthOfLayout, (void *) &sampleText, 1, lengthsArray, styles, 0, nil, nil, nil, &layoutPosition); /* dispose of style object now that it is in the layout shape */ for (loop = 0; loop < kTotalNumOfPieces; loop++) GXDisposeStyle(styles[loop]);This code results in the layout shape shown in Figure 3-20.
The recipes in Chapter 7, "Handling Typography," describe how you can allow the user to select and edit this layout shape.
Editing Typographic Shapes
You can edit the geometry of a typographic shape after you have created the shape. For example, theGXSetText
andGXSetTextParts
functions allow you to replace all or part of a text shape's geometry, respectively.Similarly, the
GXSetGlyphs
andGXSetGlyphParts
functions allow you to replace all or part of a glyph shape's geometry. You can also use functions likeGXSetGlyphPositions
to set the individual glyph positions of a glyph shape, as shown in Figure 3-21.Figure 3-21 Editing glyph positions
Similarly, you can use the function
GXSetGlyphTangents
to set the individual glyph rotations of a glyph shape, as shown in Figure 3-22.Figure 3-22 Editing glyph tangents
Layout shapes allow you more sophisticated typographic control, which you can modify with the function
GXSetLayoutParts
.Note that a layout shape represents a single line of text. QuickDraw GX provides a group of functions, such as
GXGetLayoutBreakOffset
,GXGetLayoutRangeWidth
, andGXGetNewLayoutFromRange
, that help you
locate line breaks so that you can break a long string of text into separate
layout shapes.See the section "Typographic and Layout Styles," beginning on page 112 for information about which style properties the text, glyph, and layout shapes use.
Hit-Testing Typographic Shapes
QuickDraw GX provides two functions you can use to hit-test typographic shapes:
Using the
- The
GXHitTestShape
function allows you to hit-test any of the typographic shapes.- The
GXHitTestLayout
function provides specific typographic information when hit-testing a layout shape.
GXHitTestShape
function, you can determine if you have hit
Figure 3-23 shows an example of hit-testing a glyph shape.
- the bounding rectangle of the shape
- the bounding box of a glyph
- the first half of the bounding box of a glyph
- the second half of the bounding box of a glyph
Figure 3-23 Hit-testing a text or glyph shape
You can use the
GXHitTestLayout
function when hit-testing a layout shape. QuickDraw GX also provides a related group of functions, such asGXGetLayoutCaret
andGXGetLayoutHighlight
, that you can use for selecting and highlighting text within a layout shape.You can find an example of hit-testing and editing a layout shape in Chapter 7, "Handling Typography."
Main | Page One | What's New | Apple Computer, Inc. | Find It | Contact Us | Help